package utils

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/linclaus/stock/pkg/common/util"

	"github.com/linclaus/stock/pkg/db"
	stock_model "github.com/linclaus/stock/pkg/model"
	"github.com/linclaus/stock/pkg/weixin/model"
)

var DefaultMaxStrategiesNum int
var HOST string

func init() {
	initRootNode()
	initEmailNode()
	initEmailAddOrUpdateNode()
	initStrategyNode()
	initStrategyAddNode()
	initStrategyDeleteNode()
	initStrategyAlertsNode()
}

func initRootNode() {
	model.RootNode = model.Node{
		Name: "root",
		Handler: func(input, openId string, output *[]string) model.Node {
			switch input {
			case "1":
				return model.EmailNode
			case "2":
				return model.StrategyNode
			case "3":
				ufo := GetUserInfo(openId)
				for _, msg := range ufo.String() {
					*output = append(*output, msg)
				}
				return model.RootNode
			case "4":
				return model.StrategyAlertsNode
			default:
				return model.RootNode
			}
		},
		CommandList: []string{
			"1: 邮箱管理",
			"2: 告警策略管理",
			"3: 获取我的信息",
			"4: 获取我的告警通知",
		},
	}
}

func initEmailNode() {
	model.EmailNode = model.Node{
		Name: "email",
		Handler: func(input, openId string, output *[]string) model.Node {
			switch input {
			case "0":
				return model.RootNode
			case "1":
				return model.EmailAddOrUpdateNode
			case "2":
				user, err := db.UserMgr.GetUserByOpenId(openId)
				if err == nil {
					if user.Email == "" {
						*output = append(*output, "【暂未绑定邮箱】")
					} else {
						*output = append(*output, "【您的邮箱邮箱为】："+user.Email)
					}
				}
				return model.EmailNode
			default:
				*output = append(*output, "【输入有误，请重新输入】")
				return model.EmailNode
			}

		},
		CommandList: []string{
			"0: 返回上一级",
			"1: 添加或修改邮箱",
			"2: 查询当前邮箱",
		},
	}
}

func initEmailAddOrUpdateNode() {
	model.EmailAddOrUpdateNode = model.Node{
		Name: "emailAddOrUpdate",
		Handler: func(input, openId string, output *[]string) model.Node {
			switch input {
			case "0":
				return model.EmailNode
			default:
				if VerifyEmailFormat(input) {
					if exist, _ := db.UserMgr.UserEmailExist(input); exist {
						*output = append(*output, "【邮箱已被使用】")
						return model.EmailNode
					}
					user, _ := db.UserMgr.GetUserByOpenId(openId)
					if user.Email == "" {
						user := stock_model.User{
							Email:          input,
							MaxStrategyNum: DefaultMaxStrategiesNum,
							OpenId:         openId,
						}
						db.UserMgr.CreateUser(&user)
						*output = append(*output, "【邮箱添加成功】")
					} else {
						userStrategies, _ := db.UserStrategyMgr.GetUserStrategyByUserId(user.Id)
						for _, us := range userStrategies {
							s := util.ParseStringToStrategy(us.StrategyId)
							s.ContactType = "email"
							s.ContactValue = user.Email
							s.Code = us.Code
							DeleteStrategy(s)
						}
						user.Email = input
						db.UserMgr.UpdateUser(&user)
						*output = append(*output, "【邮箱修改成功】")
					}
					return model.EmailNode
				} else {
					*output = append(*output, "【邮箱格式不正确】")
					return model.EmailAddOrUpdateNode
				}
			}
		},
		CommandList: []string{
			"【注意：邮箱更改会导致已有告警策略失效】",
			"【请输入您的邮箱】",
			"0: 退出邮箱绑定",
		},
	}
}

func VerifyEmailFormat(email string) bool {
	pattern := `\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*` //匹配电子邮箱
	reg := regexp.MustCompile(pattern)
	return reg.MatchString(email)
}

func initStrategyNode() {
	model.StrategyNode = model.Node{
		Name: "strategy",
		Handler: func(input, openId string, output *[]string) model.Node {
			user, _ := db.UserMgr.GetUserByOpenId(openId)
			if user.Email == "" {
				*output = append(*output, "【请先绑定邮箱】")
				return model.EmailAddOrUpdateNode
			}
			switch input {
			case "0":
				return model.RootNode
			case "1":
				userStrategies, _ := db.UserStrategyMgr.GetUserStrategyByUserId(user.Id)
				if len(userStrategies) >= user.MaxStrategyNum {
					*output = append(*output, fmt.Sprintf("【对不起,您最多只能创建%d个策略】", user.MaxStrategyNum))
					return model.StrategyNode
				}
				return model.StrategyAddNode
			case "2":
				userStrategies, _ := db.UserStrategyMgr.GetUserStrategyByUserId(user.Id)
				if len(userStrategies) == 0 {
					*output = append(*output, "【您暂时没有告警策略】")
					return model.StrategyNode
				}
				for index, strategy := range userStrategies {
					if index >= 10 {
						*output = append(*output, fmt.Sprintf("【当前最多显示10条告警策略，总共有%d条告警策略】", len(userStrategies)))
						break
					}
					si, _ := db.StockInfoMgr.GetStockInfoByNameOrCode(strategy.Code)
					*output = append(*output, fmt.Sprintf("告警策略%d: 【%s】", index, ParseStrategyIdToUserString(strategy.StrategyId, si.Name)))
				}
				return model.StrategyDeleteNode
			case "3":
				userStrategies, _ := db.UserStrategyMgr.GetUserStrategyByUserId(user.Id)
				if len(userStrategies) == 0 {
					*output = append(*output, "【您暂时没有告警策略】")
				}
				for index, strategy := range userStrategies {
					if index >= 10 {
						*output = append(*output, fmt.Sprintf("【当前最多显示10条告警策略，总共有%d条告警策略】", len(userStrategies)))
						break
					}
					si, _ := db.StockInfoMgr.GetStockInfoByNameOrCode(strategy.Code)
					*output = append(*output, fmt.Sprintf("告警策略%d: 【%s】", index, ParseStrategyIdToUserString(strategy.StrategyId, si.Name)))
				}
				return model.StrategyNode
			default:
				*output = append(*output, "【输入有误，请重新输入】")
				return model.StrategyNode
			}
		},
		CommandList: []string{
			"0: 返回上一级",
			"1: 添加告警策略",
			"2: 删除告警策略",
			"3: 查询告警策略",
		},
	}
}

func initStrategyAddNode() {
	model.StrategyAddNode = model.Node{
		Name: "strategyAdd",
		Handler: func(input, openId string, output *[]string) model.Node {
			if input == "0" {
				return model.StrategyNode
			}
			args := strings.FieldsFunc(input, util.Split)
			for _, arg := range args[0 : len(args)-1] {
				if !util.IsNum(arg) {
					*output = append(*output, "【告警策略输入格式有误】")
					return model.StrategyAddNode
				}
			}
			code := args[len(args)-1]
			si, _ := db.StockInfoMgr.GetStockInfoByNameOrCode(code)
			if si.Code == "" && PostStockByCode(code) != nil {
				*output = append(*output, "【您监控的股票不存在，请用股票代码试试】")
				return model.StrategyAddNode
			}
			if si.Code == "" {
				si, _ = db.StockInfoMgr.GetStockInfoByNameOrCode(code)
			}

			user, _ := db.UserMgr.GetUserByOpenId(openId)
			if user.Email == "" {
				*output = append(*output, "【请先绑定邮箱】")
				return model.EmailAddOrUpdateNode
			}
			switch args[0] {
			case "1":
				if len(args) != 3 {
					*output = append(*output, "【告警策略输入格式有误】")
					return model.StrategyAddNode
				}
				s := GenerateStrategy([][]string{
					[]string{">", args[1], "type002"},
				})
				s.ContactValue = user.Email
				s.ContactType = "email"
				s.Code = si.Code
				if PostStrategy(s) != nil {
					*output = append(*output, "【告警策略创建失败】")
					return model.StrategyAddNode
				}
			case "2":
				if len(args) != 3 {
					*output = append(*output, "【告警策略输入格式有误】")
					return model.StrategyAddNode
				}
				s := GenerateStrategy([][]string{
					[]string{"<", "-" + strings.Trim(args[1], "-"), "type002"},
				})
				s.ContactValue = user.Email
				s.ContactType = "email"
				s.Code = si.Code
				if PostStrategy(s) != nil {
					*output = append(*output, "【告警策略创建失败】")
					return model.StrategyAddNode
				}
			case "3":
				if len(args) != 3 {
					*output = append(*output, "【告警策略输入格式有误】")
					return model.StrategyAddNode
				}
				s := GenerateStrategy([][]string{
					[]string{">", args[1], "type001"},
				})
				s.ContactValue = user.Email
				s.ContactType = "email"
				s.Code = si.Code
				if PostStrategy(s) != nil {
					*output = append(*output, "【告警策略创建失败】")
					return model.StrategyAddNode
				}
			case "4":
				if len(args) != 3 {
					*output = append(*output, "【告警策略输入格式有误】")
					return model.StrategyAddNode
				}
				s := GenerateStrategy([][]string{
					[]string{"<", args[1], "type001"},
				})
				s.ContactValue = user.Email
				s.ContactType = "email"
				s.Code = si.Code
				if PostStrategy(s) != nil {
					*output = append(*output, "【告警策略创建失败】")
					return model.StrategyAddNode
				}
			case "5":
				if len(args) != 4 {
					*output = append(*output, "【告警策略输入格式有误】")
					return model.StrategyAddNode
				}
				s := GenerateStrategy([][]string{
					[]string{">", args[1] + "m", args[2], "type003"},
				})
				s.ContactValue = user.Email
				s.ContactType = "email"
				s.Code = si.Code
				if PostStrategy(s) != nil {
					*output = append(*output, "【告警策略创建失败】")
					return model.StrategyAddNode
				}
			case "6":
				if len(args) != 4 {
					*output = append(*output, "【告警策略输入格式有误】")
					return model.StrategyAddNode
				}
				s := GenerateStrategy([][]string{
					[]string{">", args[1] + "m", args[2], "type004"},
				})
				s.ContactValue = user.Email
				s.ContactType = "email"
				s.Code = si.Code
				if PostStrategy(s) != nil {
					*output = append(*output, "【告警策略创建失败】")
					return model.StrategyAddNode
				}
			case "7":
				if len(args) != 6 {
					*output = append(*output, "【告警策略输入格式有误】")
					return model.StrategyAddNode
				}
				s := GenerateStrategy([][]string{
					[]string{">", args[1] + "m", args[2], "type003"},
					[]string{">", args[3] + "m", args[4], "type004"},
				})
				s.ContactValue = user.Email
				s.ContactType = "email"
				s.Code = si.Code
				if PostStrategy(s) != nil {
					*output = append(*output, "【告警策略创建失败】")
					return model.StrategyAddNode
				}
			case "8":
				if len(args) != 6 {
					*output = append(*output, "【告警策略输入格式有误】")
					return model.StrategyAddNode
				}
				s := GenerateStrategy([][]string{
					[]string{">", args[1] + "m", args[2], "type004"},
					[]string{">", args[3] + "m", args[4], "type003"},
				})
				s.ContactValue = user.Email
				s.ContactType = "email"
				s.Code = si.Code
				if PostStrategy(s) != nil {
					*output = append(*output, "【告警策略创建失败】")
					return model.StrategyAddNode
				}
			default:
				*output = append(*output, "【请选择正确的告警策略类型】")
				return model.StrategyAddNode
			}
			*output = append(*output, "【告警策略创建成功】")
			return model.StrategyNode
		},
		CommandList: []string{
			"【请输入您的告警策略，格式为：告警类型,参数,股票名称】",
			"0: 返回上一级",
			"1: 日涨幅到达某阈值（百分比） 【如：1,5,贵州茅台】",
			"2: 日跌幅到达某阈值（百分比） 【如：2,5,贵州茅台】",
			"3: 股票价格上涨到某阈值（价格） 【如：3,2000,贵州茅台】",
			"4: 股票价格下跌到某阈值（价格） 【如：4,2000,贵州茅台】",
			"5: 股票在某时长（分钟）内涨幅超过某阈值（百分比） 【如：5,5,3,贵州茅台】",
			"6: 股票在某时长（分钟）内跌幅超过某阈值（百分比） 【如：6,5,3,贵州茅台】",
			"7: 股票在某时长（分钟）内涨幅超过某阈值（百分比），并且某时长内（分钟）又下跌了另一阈值（百分比） 【如：7,5,3,1,1,贵州茅台】",
			"8: 股票在某时长（分钟）内跌幅超过某阈值（百分比），并且某时长内（分钟）又上涨了另一阈值（百分比）【如：8,5,3,1,1,贵州茅台】",
		},
	}
}

func initStrategyDeleteNode() {
	model.StrategyDeleteNode = model.Node{
		Name: "StrategyDelete",
		Handler: func(input, openId string, output *[]string) model.Node {
			user, _ := db.UserMgr.GetUserByOpenId(openId)
			if user.Email == "" {
				*output = append(*output, "【请先绑定邮箱】")
				return model.EmailAddOrUpdateNode
			}
			userStrategies, _ := db.UserStrategyMgr.GetUserStrategyByUserId(user.Id)
			switch input {
			case "all":
				for index, us := range userStrategies {
					s := util.ParseStringToStrategy(us.StrategyId)
					s.ContactType = "email"
					s.ContactValue = user.Email
					s.Code = us.Code
					if DeleteStrategy(s) != nil {
						*output = append(*output, fmt.Sprintf("【告警策略%d删除失败】", index))
					}
					fmt.Printf("Delete Strategy: %s\n", us.StrategyId)
					*output = append(*output, "【告警策略删除成功】")
				}
				return model.RootNode
			case "-1":
				return model.StrategyNode
			default:
				index, err := strconv.ParseInt(input, 10, 64)
				if err != nil || index < 0 || index >= int64(len(userStrategies)) {
					*output = append(*output, "【请选择正确的告警策略】")
					return model.StrategyDeleteNode
				}
				us := userStrategies[index]
				s := util.ParseStringToStrategy(us.StrategyId)
				s.ContactType = "email"
				s.ContactValue = user.Email
				s.Code = us.Code
				if DeleteStrategy(s) != nil {
					*output = append(*output, "【告警策略删除失败】")
					return model.StrategyDeleteNode
				}
				fmt.Printf("Delete Strategy: %s\n", us.StrategyId)
				*output = append(*output, "【告警策略删除成功】")
				return model.StrategyNode
			}
		},
		CommandList: []string{
			"all: 删除所有的告警策略",
			"【请选择您的告警策略】",
			"-1: 返回上一级",
		},
	}
}

func initStrategyAlertsNode() {
	model.StrategyAlertsNode = model.Node{
		Name: "StrategyAlertsNode",
		Handler: func(input, openId string, output *[]string) model.Node {
			user, _ := db.UserMgr.GetUserByOpenId(openId)
			if user.Email == "" {
				*output = append(*output, "【请先绑定邮箱】")
				return model.EmailAddOrUpdateNode
			}
			if input == "-1" {
				return model.RootNode
			}
			now := time.Now()
			i, err := time.ParseDuration(input + "h")
			if err != nil {
				*output = append(*output, "【您输入格式有误】")
				return model.StrategyAlertsNode
			}
			t := now.Add(-1 * i)
			userStrategies, _ := db.UserStrategyMgr.GetUserStrategyByUserIdAndAlertd(user.Id, t)
			if len(userStrategies) == 0 {
				*output = append(*output, fmt.Sprintf("【最近%s小时没有告警事件】", input))
			}
			for index, strategy := range userStrategies {
				if index >= 10 {
					*output = append(*output, fmt.Sprintf("【当前最多显示10条告警通知，总共有%d条告警通知】", len(userStrategies)))
					break
				}
				si, _ := db.StockInfoMgr.GetStockInfoByNameOrCode(strategy.Code)
				url := fmt.Sprintf("%s/image/%s", HOST, strategy.Code)
				t := fmt.Sprintf("%d-%02d-%02d %02d:%02d:%02d\n", strategy.LastAlertTime.Year(), strategy.LastAlertTime.Month(), strategy.LastAlertTime.Day(), strategy.LastAlertTime.Hour(), strategy.LastAlertTime.Minute(), strategy.LastAlertTime.Second())
				*output = append(*output, fmt.Sprintf("【告警通知%d: 时间：%s, 策略: %s， 快照：%s】", index+1, t, ParseStrategyIdToUserString(strategy.StrategyId, si.Name), url))
			}
			return model.StrategyAlertsNode
		},
		CommandList: []string{
			"【获取最近多长时间(小时)的告警通知？如：1（表示最近1小时）】",
			"-1: 返回上一级",
		},
	}
}
